package org.kele.asyncservlet.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
public class DemoController {

    @GetMapping("/test-async")
    public Callable<String> doTestAsync() {
        return () -> {
//            throw new RuntimeException("i am wrong"); // 此处异常可以被 restcontrolleradvice 类捕获并处理；
            TimeUnit.MILLISECONDS.sleep(100L);
            return "ok kele 呵呵哒";
        };
    }

    @GetMapping("/test-sync")
    public String doTestSync() {
        try {
            TimeUnit.MILLISECONDS.sleep(100L);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        return "ok kele 呵呵哒 sync";
    }

    @GetMapping("/test-async2")
    public Object doTestAsync2() {
        log.info("handle biz ...thread block");
        try {
            TimeUnit.SECONDS.sleep(10L);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return "ok kele 呵呵哒";
    }

    @GetMapping("/test-inherit")
    public Callable<Object> doTestInherit() {
        log.info("test inherit");
        return () -> {
            RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
            log.info("线程私有变量：{}", requestAttributes); // 成功获取； 不用使用taskdecorator， mvc自动帮我们传递上下文
            return "ok ahah";
        };
    }

    @Async
    @GetMapping("/test-async-annotation")
    public CompletableFuture<String> testAsyncAnnotation() {
        // 使用@async 必须要用CompletableFuture包裹一层；  如果不在controller层， 可以返回原生类型；
        log.info("do.. 线程私有变量：{}", RequestContextHolder.currentRequestAttributes());

//        throw new RuntimeException(".... failed");//  此处异常可以被 restcontrolleradvice 类捕获并处理；
        return CompletableFuture.completedFuture("ok haha大");
    }
}
